{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Card Abstraction Visualization\n",
    "Background: I first went through `abstraction_exploration.ipynb` to better understand how many clusters I should be using for K-Means clustering, concluding that 100 clusters per game stage was a good number using the elbow method.\n",
    "\n",
    "Using `abstraction.py`, I then randomly generated 100,000 hands per game stage (flop/turn/river), and then generated the clusters on this data using K-Means Clustering using the euclidean distance, which are found in the `data/clusters` folder. \n",
    "\n",
    "Now, in this notebook, I attempt to visualize the clusters generated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import joblib\n",
    "from sklearn.cluster import KMeans\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import sys\n",
    "sys.path.append('../src')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Flop Visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "flop_kmeans = joblib.load('../kmeans_data/kmeans/flop/kmeans_1719903872_samples=10000_bins=10.joblib')\n",
    "flop_raw_data = np.load('../kmeans_data/distributions/flop/1719903872_samples=10000_bins=10.npy')\n",
    "flop_cards = np.load('../kmeans_data/cards/flop/1719903872_samples=10000_bins=10.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Convert histograms to EHS\n",
    "ehs_flop_raw_data = (flop_raw_data * np.array([0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95])).sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 5, 25, 38, ..., 39, 25,  9], dtype=int32)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kmeans = flop_kmeans\n",
    "assert(len(kmeans.cluster_centers_) == 50)\n",
    "flop_kmeans_centroids = kmeans.cluster_centers_\n",
    "\n",
    "flop_raw_data_classes = kmeans.predict(flop_raw_data)\n",
    "flop_raw_data_classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading KMeans Flop Classifier kmeans_1719903872_samples=10000_bins=10.joblib\n",
      "Loading KMeans Turn Classifier kmeans_1719904417_samples=10000_bins=10.joblib\n"
     ]
    }
   ],
   "source": [
    "from abstraction import calculate_equity_distribution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 10 artists>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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I488ovnz5+vFF1/UddddF1vz8MMPa2hoSPfee69Onjypm266Se3t7crMzJyAUzSD1WpVfX39Od/KwsXB+31p8X5fWrzflx7vefKlRS/kZ4kAAACSiN8lBAAAjEewAAAA4xEsAADAeAQLAAAwHsFyibS0tMjhcCgzM1NOp1NdXV3JHikl+Xw+LV26VDNmzNDs2bO1atUqvfPOO8kea8pobGyMfVQBLo5jx47pL//yL3XllVcqKytLCxcu1GuvvZbssVLSyMiINm/erMLCQmVlZWnu3LlqaGi4oN97g4lHsFwCbW1t8nq9qq+vV09PjxYvXiy3262+vr5kj5ZyXn75Zd1///06cOCAXnrpJX366adavny5hoaGkj1aynv11Vf14x//WIsWLUr2KCnr//7v/3TjjTfqz/7sz/TP//zPeuutt/Tkk09q5syZyR4tJW3dulU7d+5Uc3Oz3n77bW3dulXbtm3Tj370o2SPNiXxY82XgNPp1NKlS9Xc3Czps08HLigo0AMPPKCampokT5fa+vv7NXv2bL388su65ZZbkj1Oyjp16pSWLFmip59+Wk888YRKSkrU1NSU7LFSTk1Njf7jP/5D//7v/57sUaaEb37zm7LZbPq7v/u72LE77rhDWVlZeuGFF5I42dTEFZaLbHh4WN3d3XK5XLFj6enpcrlc6uzsTOJkU8Pg4KAkadasWUmeJLXdf//9WrlyZdx/55h4//iP/6iysjLdddddmj17tq6//nrt2rUr2WOlrBtuuEF+v19/+tOfJEn/+Z//qVdeeUUrVqxI8mRT06T8bc2TycDAgEZGRmKfBHyGzWbT4cOHkzTV1BCJRLRx40bdeOONcZ+sjIm1b98+9fT06NVXX032KCnvv//7v7Vz5055vV498sgjevXVV/XXf/3XysjI0Jo1a5I9XsqpqalRKBRScXGxLBaLRkZG9L3vfU933313skebkggWpKz7779fb775pl555ZVkj5Kyjhw5og0bNuill15KqV+lYapIJKKysjJ9//vflyRdf/31evPNN9Xa2kqwXAQ///nP9dOf/lR79+7Vtddeq0OHDmnjxo3Kz8/n/U4CguUiy83NlcViUTAYjDseDAZlt9uTNFXqW79+vX7961/r97//vb761a8me5yU1d3drb6+Pi1ZsiR2bGRkRL///e/V3NyscDgsi8WSxAlTS15enhYsWBB37JprrtHf//3fJ2mi1LZp0ybV1NSoqqpKkrRw4UL9z//8j3w+H8GSBNzDcpFlZGSotLRUfr8/diwSicjv96u8vDyJk6WmaDSq9evX61e/+pX+7d/+TYWFhckeKaXddttt+q//+i8dOnQo9igrK9Pdd9+tQ4cOESsT7MYbbzznx/T/9Kc/6Wtf+1qSJkptp0+fjvtlvpJksVgUiUSSNNHUxhWWS8Dr9WrNmjUqKyvTsmXL1NTUpKGhIXk8nmSPlnLuv/9+7d27V//wD/+gGTNmKBAISJJycnKUlZWV5OlSz4wZM865P2j69Om68soruW/oIvibv/kb3XDDDfr+97+vv/iLv1BXV5eeeeYZPfPMM8keLSV961vf0ve+9z1dddVVuvbaa/X6669rx44d+qu/+qtkjzY1RXFJ/OhHP4peddVV0YyMjOiyZcuiBw4cSPZIKUnSqI+f/OQnyR5tyrj11lujGzZsSPYYKeuf/umfotddd13UarVGi4uLo88880yyR0pZoVAoumHDhuhVV10VzczMjBYVFUUfffTRaDgcTvZoUxKfwwIAAIzHPSwAAMB4BAsAADAewQIAAIxHsAAAAOMRLAAAwHgECwAAMB7BAgAAjEewAAAA4xEsAADAeAQLAAAwHsECAACMR7AAAADj/T+1tenjUBc03gAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cards = '7s 9s 8h 3c Ts'\n",
    "# cards = '6s 3s 8h 5s Js'\n",
    "plt.bar([i for i in range(10)], calculate_equity_distribution(cards.split(' ')[:2], cards.split(' ')[2:]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 10 artists>"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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P1bVDayNjY1ZunRpBgcHp/ZNTk5mcHAwK1asOOkxK1asmLY+SZ544okZ1wMAF5aqf03T19eXtWvXpqurK8uXL8/AwECOHTuW3t7eJMmaNWuycOHC9Pf3J0nuvPPO3HLLLfn0pz+dVatW5bHHHss3vvGNPPTQQ2f3lQAAs1LVMbJ69eocOXIkmzZtyvDwcDo7O7N79+6pm1QPHjyY+vpXL7jcdNNNefTRR/MHf/AH+ehHP5qf/MmfzBe/+MVcd911Z+9VvAE0NTVl8+bNJ/x6iXPD+T6/nO/zy/k+v5zv8uoqr/d+GwCAc8jfpgEAihIjAEBRYgQAKEqMAABFiZGzYPv27eno6Ehzc3O6u7uzZ8+e0iPVpP7+/ixbtixz587NFVdckVtvvTXPP/986bEuGFu2bEldXV3uuuuu0qPUrBdffDG//uu/nssvvzxz5szJ9ddfn2984xulx6pJExMT+cM//MO8/e1vz5w5c3LNNdfknnvued2/ocK5IUbO0K5du9LX15fNmzdn3759WbJkSVauXJnDhw+XHq3mfOUrX8ntt9+er3/963niiSfywx/+MO973/ty7Nix0qPVvKeffjqf+cxn8q53vav0KDXr+9//fm6++ea86U1vyt///d/n29/+dj796U9n/vz5pUerSffdd18efPDBbNu2Ld/5zndy33335ZOf/GQeeOCB0qNdkLy19wx1d3dn2bJl2bZtW5IffSJte3t77rjjjmzYsKHwdLXtyJEjueKKK/KVr3wl73nPe0qPU7N+8IMf5MYbb8yf/umf5o//+I/T2dmZgYGB0mPVnA0bNuRf//Vf8y//8i+lR7kg/OIv/mJaW1vz2c9+dmrfBz7wgcyZMyePPPJIwckuTK6MnIHjx49n79696enpmdpXX1+fnp6eDA0NFZzswjA6OpokueyyywpPUttuv/32rFq1atq/c86+v/mbv0lXV1d+9Vd/NVdccUVuuOGGPPzww6XHqlk33XRTBgcH893vfjdJ8m//9m956qmn8gu/8AuFJ7swvSH/au9scfTo0UxMTEx9+uyPtba25rnnnis01YVhcnIyd911V26++eaa+zTfN5LHHnss+/bty9NPP116lJr3X//1X3nwwQfT19eXj370o3n66afzO7/zO2lsbMzatWtLj1dzNmzYkLGxsSxatCgNDQ2ZmJjIvffem9tuu630aBckMcKsdPvtt+fZZ5/NU089VXqUmnXo0KHceeedeeKJJ9Lc3Fx6nJo3OTmZrq6ufOITn0iS3HDDDXn22WezY8cOMXIO/OVf/mX+4i/+Io8++mje+c53Zv/+/bnrrrty5ZVXOt8FiJEzsGDBgjQ0NGRkZGTa/pGRkbS1tRWaqvatX78+f/d3f5evfvWreetb31p6nJq1d+/eHD58ODfeeOPUvomJiXz1q1/Ntm3bMj4+noaGhoIT1pa3vOUtWbx48bR973jHO/LXf/3XhSaqbR/5yEeyYcOGfPCDH0ySXH/99XnhhRfS398vRgpwz8gZaGxszNKlSzM4ODi1b3JyMoODg1mxYkXByWpTpVLJ+vXr84UvfCH/9E//lLe//e2lR6ppP/uzP5tnnnkm+/fvn9q6urpy2223Zf/+/ULkLLv55ptPeKv6d7/73bztbW8rNFFte+WVV6b9UdckaWhoyOTkZKGJLmyujJyhvr6+rF27Nl1dXVm+fHkGBgZy7Nix9Pb2lh6t5tx+++159NFH86UvfSlz587N8PBwkqSlpSVz5swpPF3tmTt37gn347z5zW/O5Zdf7j6dc+B3f/d3c9NNN+UTn/hEfu3Xfi179uzJQw89lIceeqj0aDXp/e9/f+69995cddVVeec735lvfvOb2bp1a37zN3+z9GgXpgpn7IEHHqhcddVVlcbGxsry5csrX//610uPVJOSnHT7sz/7s9KjXTBuueWWyp133ll6jJr1t3/7t5Xrrruu0tTUVFm0aFHloYceKj1SzRobG6vceeedlauuuqrS3Nxcufrqqysf+9jHKuPj46VHuyD5nBEAoCj3jAAARYkRAKAoMQIAFCVGAICixAgAUJQYAQCKEiMAQFFiBAAoSowAAEWJEQCgKDECABQlRgCAov4PxFfZnxGDC9MAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cards = 'Ah 7s Qc 3h 5s'\n",
    "plt.bar([i for i in range(10)], calculate_equity_distribution(cards.split(' ')[:2], cards.split(' ')[2:]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['7s 9s 8h 3c Ts', '6s 3s 8h 5s Js', '8h 5d 6h Qh 4h',\n",
       "       '5s 7s 2s Ts 4c', '2s 9s 8s 5s 4d', '3d 8d Qh 5d 9d',\n",
       "       'Jd 5d 7c 6h 4d', 'Js 3s Ks Tc 9c', '9s 8s Tc 5s 3s',\n",
       "       '9h Th 3s 8c 7c', '8s 9c Js 4d Td', 'Td 9c 4c 7c 8s',\n",
       "       '8s 9h Qs Td 6h', '3c 8c 6c 2c Ah', '8c 6s 7s 5d 5c',\n",
       "       '6c 9c 4c Td 3c', '8d Ks 6s 4h 5h', '6c Ts 5c 7h 8s',\n",
       "       'Jd 6c 4c 3c 5d', '5s 6s Ac Ts 3s', '8s 6s 9h 7h Ks',\n",
       "       '5s 3s 2c 4s 9s', '8s 7s Td Ah 9h', 'Td 7s 9s 5d 8d',\n",
       "       '8d 7h 5d 9d Js', '5c 9c Jc 2s 3c', '7c 2c 6d 8c 4c',\n",
       "       '6d Td Ad 8h 7c', '7c Ts 9s 3d 8c', 'Jc 9h 6c 8s Td',\n",
       "       '9h Ts 8d 6c Jd', 'Td 6s 7d 4d 3d', '6c Jd 9c 8s Th',\n",
       "       '8s 3s 7s Qs 5h', '2s 4s Ts As 3h', '5h 4h Ah 2d 7h',\n",
       "       '8h 2h 4h 9s Qh', '7c 9h 4c Ts 8c', '7s Td 6s 8d Ad',\n",
       "       'Th 4d 9c Js 8h', '8s 4s Jh 6s 2s', '8c 9s Jc 7d 6c',\n",
       "       '9s Jc 5c Tc 7s', '7c 6c 3c 9d 2c', '8c 9s 6c 7s Js',\n",
       "       '7d 4d 9c 5d 9d', 'Ts 8s 6d Jd 9h', '6h 8c 9d 7h Jh',\n",
       "       '5s 9d 8s 7s Jc', 'Ts 8c 9d 5c 7c', '8h 7d Ah Tc 9d',\n",
       "       'Js 5h 6c 3c 4h', '4c 9d 8c 7h Td', '8c 3c Kc Jh 4c',\n",
       "       'Jd Qd 6s 8h Th', '6d Ts 4h 7c 8h', '6d Jh 4s 7c 5c',\n",
       "       '9d 7d 6s Ac 8d', '9d 7d 8h Ac 6h', 'Jd 5c 3h 6s 4s',\n",
       "       '4d Ts 3s 5s 6h', '8d 9d 4d 3d 7h', '7d 8h Ts 5h 9h',\n",
       "       'Th 4s Jh 8d 9c', '6d 5d 7d 3s Jd', '7c Th 9c 3h 8c',\n",
       "       'Jh 9d 8d 5d 7c', '6c 8h Qc 7s 9d', 'Td Jh 9s 6c 8s',\n",
       "       '9s Ts Qh 8d 2s', '7h 6c 9d 8s Ah', '8h 7s Ts 9c 2d',\n",
       "       'Td 3d 9h 2d 6d', '7h 3h Jh Kh 4d', '9s 8c Ts 4d 7c',\n",
       "       '8c Ts 2h 7s 9h', '9h 3h 5d Jh 7h', 'Jh 7c 5c Td 9c',\n",
       "       '7s 6d 8h 8s 5d', '2c 4c 6c 3c Kh', '6c Ts 8s 5s 7d',\n",
       "       '6h 7h 9c 8h 3s', '9s 8s 7s 6c 4h', 'Ts 2s Qs 6s 7h',\n",
       "       '7h 6h 3d 9h 4h', '2c 9c Kc 3s 8c', '7s 5s 6d Ks As',\n",
       "       '8d 4d 3d As 9d', '5c Js 3d 4h 2d', 'Ts 2h 8h 9c Jd',\n",
       "       '2c 5c Tc Jc Jh', '8h 6s 7s 5s 5c', '3c 6c Jc 2c Ks',\n",
       "       '2h 9h 7h 8h 5s', '8d 2d 3d Qs Jd', '9h 7d 6c 8d 2d',\n",
       "       'Th 3h 2h 7c 4h', '8h 9h 5h 4s 2h', '7d 6c 8c 9d Kd',\n",
       "       '6c 9c 8s Qh 7h', 'Th Jd 7s 9d 4s', 'Jh 4h Td Qd 9c',\n",
       "       '8d 7c 6h 5s Qc', '7s Ts 9s 4h 8h', '4s Jd 2d 5h 3s',\n",
       "       '8d 5s Td 7s 6d', '9s 7h 5h Js 8s', '2d 4d As 3d Qd',\n",
       "       '2h 5h 6c 4h Qh', '9s 7s 5s 2h Qs', '5h Js 6h 4s 3d',\n",
       "       '2h 9h 7h Kh 8s', '7d 8h 5h 9d Jc', '3c Jd 2d 5s 4s',\n",
       "       '5h 4h Ts Jh 7h', '6c 7s 8d 9c Ad', '5s 9s Ts 7d 4s',\n",
       "       '8c Tc 7d Kh Js', '7d 2d Ad 4c 9d', '4d 9d 8d As 2d',\n",
       "       'Th Qh 8c 7d 6h'], dtype='<U14')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Very drawy kind of hands\n",
    "flop_cards[np.where(flop_raw_data_classes == 32)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Ah 7s Qc 3h 5s', '5d Ac Ks 3s Td', '2h 2c Jd Kh 6h',\n",
       "       '6d As Tc Qh 4d', 'Qd 8h Ks As 3h', 'Kc 2d Qd Ad 3h',\n",
       "       'Kc 5d 6h Ac 7s', 'Ac 5d Qc 6s 2h', '2c 2h 7h 6d 6s',\n",
       "       'Kd 4c 5h 8s 5c', '3h Ks 4h 5c Ah', '2c 2s Ks 8c Qc',\n",
       "       'Ah 4c 3s 6d Jc', '3c 3h 8d 9c 4s', '3d 3h 7s Ac 6h',\n",
       "       '6d Ac 5s 2c Jh', 'Ac 8d Qc 9h 4d', 'Kd Td 2s 2h 4h',\n",
       "       'Kh 9c 3d 8s Ah', 'Ac 9s 4c Ks 8h', '2c 2s 7d 7c 5s',\n",
       "       'Ah 5d 6c Qs 8d', '2d Kh 6d 6c 4s', 'Js Ks 4h Tc 9h',\n",
       "       '7c Js Ah 8s 8c', '8h Qc Kc As 4d', 'Ah 8d 2h Qd 3c',\n",
       "       '5d 2s 5h 7h Ah', 'Kd 8s 6d 4s 4h', '3h 3c 5h 8s Th',\n",
       "       '9s Jc 5c 7c Qc', '2c 2h Tc 5d Ad', 'Qd 9d 7c Jc Kh',\n",
       "       '4c 4h 9c Ah Ts', 'Jc Ah 2d 9h 5s', 'Qs Ac 3s 8d 9d',\n",
       "       'As 2s Kd Th 5c', 'Td Kc Qs 2h 9h', '3c Ah 6d Jc 5c',\n",
       "       '4d As Qd 7d 6s', '9c 2c 2d 6s 4s', 'Kh 4d 3d 7c 3c',\n",
       "       '8h Ac 2c 3d Ks', 'As 2h 5d 3c Qs', '3s 3d Qd 9s 7d',\n",
       "       'Ad 9h Qs 3h 5d', '6d Ah Kc 5s Qh', '4s 4d 9h 5s Td',\n",
       "       '6c Ad 7c 9s Th', '4d 4h 5c Kd Qc', 'Kd 2c Qc 8h Qd',\n",
       "       '6c Ah 2c 9c 5s', '2s Kc 8s 8h 3c', 'Td Qh 2h 8h 2d',\n",
       "       '8c Ah Kd 3h 9d', 'Ah 8h 5c 4s Qd', '2d 2s Qc Ks 9s',\n",
       "       'Kc 9d 3d Qs Js', '7h As Kc Qc 6s', 'Jh Ac 6s Td 8d',\n",
       "       '9h Qd 5h Td Kc', '3d 3c Td Js 7d', '2d 2h Ks 8c 3d',\n",
       "       'Kd 3s Ts Tc 5d', '7h Ad 3c Qd 6h', '6d Ac Qd Ks 9c',\n",
       "       '9h As 3c 2h 7c', 'Qs Kc Js 3s 8d', '6c Ad Kc 3h 2c',\n",
       "       '7s Qc Ad 2h Ah', '2d 2h 8s 4d Qc', '3s 3c Kd Js 5c',\n",
       "       '6d Qs 5s Js 8s', '7c Ah 8h 2d Jc', 'As 8s Qd Kh 2h',\n",
       "       'Qd Js 9d Ks 4h', '8d Qd Ac As 5c', '6d Kh 8d 9s Ad',\n",
       "       '2c 4h 9s 2s 3s', '2c Ks 9c 5d 9s', 'Jc Td 8h Kd Ks',\n",
       "       '7c Kh Ts Th 3s', '3h 3c Qh Td 8s', 'Ks 9s Ac 2d Tc',\n",
       "       '8c Ac 2h 7h 4s', 'Ad 4c Th Kc 3d', '7s Ac 3h 4s Kd',\n",
       "       'Qs Ad 4h 3h 8s', 'Kh 7c Ts 9h As', '5d As Qc 9d 7d',\n",
       "       '4h Kd Ac 8h 2s', '2d 2c Js Ah 7d', '4c 4d Td Ks As',\n",
       "       '7s Jc 8s 8h 8c', '2d Qc Kh Ad 5s', 'Qc Kh 9d 8c Jc',\n",
       "       '9h Qh 2d 2h Jc', '6h Ad 7c 3s 9d', 'Qs 9c Js 6h Kc',\n",
       "       'Kd 9s 7h 2h Ac', 'Ac 4d 5h Qs 8c', 'Th 7c Ac Jh Qs',\n",
       "       '2s 2d 8s Ad 5s', '2s 2d Kc Ad 4c', '2c Kh 4c Ad 5h',\n",
       "       '2s 2c Js Ac 8c', '6h Kc 5s 5d Qs', 'Kc 9s 7d As 2c',\n",
       "       '3c 3d 5h As 8d', '8d Ks 5d 7h 9d', 'As 6h 7h 2s 9d',\n",
       "       '6c Ad 5c 9d 2c', 'Ad Jd 5s 2c 8h', 'Ah 5s Qd 3h Kd',\n",
       "       '3s 3d Qc 7d 4c', 'Ks Qh 4h 9d 2h', 'Kd Tc 8h 6h 6c',\n",
       "       'As 3c 4c Qh Jd', '7d Qs 4c As Ah', 'Kd 8c Qc 9c Th',\n",
       "       'Td As 9c 4c 3s', '3c 3s 7s 6d 5h', 'Ac 9s Qd 3d Kc',\n",
       "       '2h Ah Qs Jc Tc', 'Qc Ad 6c 3c 9s', '9c Ac Qd 7h Kh',\n",
       "       '2d 2h Kd 3s 7h', 'Kd 9h Ah Jc 6c', 'As 2c Qh Kc 3c',\n",
       "       'Ad 3s Kh Js 5h', 'Qh 3d 6s 6c Ac', 'Ad 5s Jc 6h 8s',\n",
       "       '3s 2h 9c 3c Kc', 'Jd Kc 7s 2d As', 'Tc Ah 6s 8c 7s',\n",
       "       'Ah 8h 2c 3s Qd', 'Ks As 6h 9c 3d', '3c 2c 2h Ah 8h',\n",
       "       'Qs Jh 8s 8h 3h', '5d Ac 6d 2h 9s', '8d Kc 2s Qs Ad',\n",
       "       'As 7d 5h Kh 8c', 'Kd 4d 8s Th 8c', 'Qc 9d 8s Kh As',\n",
       "       '2h 7s 4c 3d 2d', '2c Ts 5d 4s 2d', 'Ac Ts 9h 3h Kd',\n",
       "       'Kd 5h 8h Td Ts', 'Kc 5h 7h Ad 8h', 'Tc As 5c 4h 9d',\n",
       "       'Ah 6c Qd 5c 4h', '6h Kc 3d Jc Jd', 'Qc 9d 7h Kd Tc',\n",
       "       'Kh 9s 6d Qh 7c', '3c 3s Ts 9s 4c', '2d 2c Qd Kd 6s',\n",
       "       '3s 3d Qh 4s 7c', 'Ac Jc Kd 9h 6h', 'Ks 4h Qd 8s Qc',\n",
       "       '5h Ad Kh 6d Jc', '3d 3s Ac Qh 7c', '8d As 6d 2d Kh',\n",
       "       '7s Ad 9h 6c 2c', '2s 2h 4s Ks 8c', 'Ac 7s 2h 3c Qc',\n",
       "       'Jh 4d 6d 6h 6c', 'Td Ac 5d 4c 2h', 'Ah 9h 4d 8s Kc',\n",
       "       'Ad 5h 6c 7h Qc', '7c Qd 3h Ah Ac', '2h 2c 6c Qs 3d',\n",
       "       'Ah 8c Jc 2c 4s', '3s 3d 9h 6d 4c', 'Th Ac 5c 4d 3h',\n",
       "       'As 6c Td 2s 4h', 'Qd 4c Ad 5s As', 'Kh Qd As 3c 5d',\n",
       "       '3c 3s Ks 9d Qc', '6d Kc 2d 3d Jd', '6h Ac 7c 9h Ks',\n",
       "       '4h Ac Kh 5d 8s', 'Tc Ks 4h 4d 6c', '3c Ks 5h 6h 5s',\n",
       "       'Ac 6d 2d Qc Kh', '3d 3h Jh 4h 7c', 'Ac 5d 7c 6h Kh',\n",
       "       '3c 3h 8d 4h 5c', 'Ah Tc 5c 9s 4h', '3h As Kc Js 4c',\n",
       "       '2c 2s Qs 9h 5d', 'Ks 4s 7c Jh Jd', '9d As Kh 8c 6h',\n",
       "       'Tc Ks 4d 4s 3d', 'Ks 9s Jd 4c Ah', 'As Js 9h 7d 4c',\n",
       "       '7s Ad 2h 3d Kh', '2d 7h 4s 3c 2c', 'As 9s Kd 2c 8d',\n",
       "       '2s 2h 3c 8h Qc', 'Kh 8d Jc As 2h', 'Kh 5c 9d 4s Ah',\n",
       "       'Kh Ts 7h 4s 9h', 'Ks Jd 7d Th 2c', 'Kh Tc 5s Jd 9d',\n",
       "       '2h 2d 4c 3s Qd', 'Ad 8s 9s Qh Kd', '8c Kc 6s 5d Ah',\n",
       "       'Ah 6d 9h Qs Kc', '5s Kd 2h 4d 4h', 'Qs Jd Tc 7c Kc',\n",
       "       'Ac 6h Qh Ts Jd', '3s Kd Js 7d Ac', 'Ah 8c 9h 2s Qd',\n",
       "       '9d Ah Qd Js 5s', '4s Ac 3c Qs Th', 'Ah 8c 7s Kd 3h',\n",
       "       '7h Ac Qh 3h 4s', '2h Th 2c 8c 3c', 'Ac 6h 5h Ts 2d',\n",
       "       '7c Ah Qs 3c Jh', 'Ah Ks 8h 9h 5c', '9h Qs 3c Kd Th',\n",
       "       '3h Th 6c 9c 3c', 'Jd 9h 8h Kd Qc', 'Qd Ac 7h 4s 9s',\n",
       "       '3c Qs 6s Kc 6d', 'Th Kd 7h 2d Js', 'Ad 9c 4s Qd 3c',\n",
       "       'As 3h 7s Qs 4c', '8h Ad Jc Kc 2s', 'Kh Jd 2h 3d Qs',\n",
       "       'Ah Ks 6c 5h 9d', 'Ah 9h 2c 7s 3c', '9d Ad Qc Th 4h',\n",
       "       '7c Jh 4c Qc Tc', 'Kc 9h 4d Jd Th', 'Qd Ad 4c Kc 6s',\n",
       "       '2s 2h 4d 3c Td', '2s Ah Tc 3s Js', '6h Ac 2s 7d Kc',\n",
       "       'Ts 2d 5h 3s 2h', '6s Ac 3h 8d 9s', 'Ah 6d Ks 2d 7h',\n",
       "       'Td Qh 2d 2s 8d'], dtype='<U14')"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Pocket 2s, Ace high kind of hands, no draws\n",
    "flop_cards[np.where(flop_raw_data_classes == 33)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The raw data is 10 dimensional, so we first run PCA to reduce this data down to 3 dimensions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "import plotly.express as px\n",
    "import plotly.graph_objects as go\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pca_3d = PCA(n_components=3) # 3D vizualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "PCs_3d = pca_3d.fit_transform(flop_raw_data)\n",
    "PCs_3d_centroids = pca_3d.fit_transform(flop_kmeans_centroids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(PCs_3d, columns=['dim1', 'dim2', 'dim3'])\n",
    "df_centoids = pd.DataFrame(PCs_3d_centroids, columns=['dim1', 'dim2', 'dim3'])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"Player Cards: ['Qc', 'Qs'], Community Cards: ['Qd', 'Kh', 'Td'], Class: 5, EHS: 0.88\",\n",
       " \"Player Cards: ['9c', 'Jh'], Community Cards: ['8h', '2s', '6h'], Class: 25, EHS: 0.39\",\n",
       " \"Player Cards: ['5d', 'Th'], Community Cards: ['3s', '6s', '9c'], Class: 38, EHS: 0.28\",\n",
       " \"Player Cards: ['7h', '9h'], Community Cards: ['8s', '4s', '9c'], Class: 7, EHS: 0.75\",\n",
       " \"Player Cards: ['8d', 'Js'], Community Cards: ['Ts', '3d', '2s'], Class: 40, EHS: 0.39\"]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "marker_text = []\n",
    "for i, card_string in enumerate(flop_cards):\n",
    "\tcards = card_string.split(' ')\n",
    "\tassert(len(cards) == 5)\n",
    "\tmarker_text.append(f'Player Cards: {cards[:2]}, Community Cards: {cards[2:]}, Class: {flop_raw_data_classes[i]}, EHS: {ehs_flop_raw_data[i]:.2f}')\n",
    "marker_text[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "' TODO:\\n- Add Title\\n- Animate rotation https://community.plotly.com/t/how-to-animate-a-rotation-of-a-3d-plot/20974\\n'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\" TODO:\n",
    "- Add Title\n",
    "- Animate rotation https://community.plotly.com/t/how-to-animate-a-rotation-of-a-3d-plot/20974\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = go.Figure()\n",
    "fig.add_trace(go.Scatter3d(x=PCs_3d[:, 0], y=PCs_3d[:,1], z=PCs_3d[:,2],\n",
    "                        hovertemplate='<b>%{text}</b><extra></extra>',\n",
    "                        text=marker_text,\n",
    "                        marker=dict(\n",
    "                            size=2,\n",
    "                            color=flop_raw_data_classes\n",
    "                        ),\n",
    "                        mode='markers',\n",
    "))\n",
    "fig.update_layout(title=dict(text=f\"Flop Abstraction ({flop_kmeans_centroids.shape[0]} Clusters)\", font=dict(size=28)), title_x=0.5, scene=dict(\n",
    "                  xaxis_title=\"Dimension 1\",\n",
    "                  yaxis_title=\"Dimension 2\",\n",
    "                  zaxis_title=\"Dimension 3\")\n",
    ")\n",
    "# fig.show()\n",
    "fig.show(renderer='browser')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Turn Visualization\n",
    "Same steps as for flop."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "kmeans_turn = joblib.load('../kmeans_data/kmeans/turn/kmeans_1719904417_samples=10000_bins=10.joblib')\n",
    "raw_data = np.load('../kmeans_data/distributions/turn/1719904417_samples=10000_bins=10.npy')\n",
    "cards = np.load('../kmeans_data/cards/turn/1719904417_samples=10000_bins=10.npy')\n",
    "\n",
    "# Convert histograms to EHS\n",
    "ehs_raw_data = (raw_data * np.array([0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95])).sum(axis=1)\n",
    "\n",
    "kmeans = kmeans_turn\n",
    "raw_data_classes = kmeans.predict(raw_data)\n",
    "kmeans_centroids = kmeans.cluster_centers_\n",
    "\n",
    "pca_3d = PCA(n_components=3) # 3D vizualization\n",
    "PCs_3d = pca_3d.fit_transform(raw_data)\n",
    "PCs_3d_centroids = pca_3d.fit_transform(kmeans_centroids)\n",
    "\n",
    "df = pd.DataFrame(PCs_3d, columns=['dim1', 'dim2', 'dim3'])\n",
    "df_centoids = pd.DataFrame(PCs_3d_centroids, columns=['dim1', 'dim2', 'dim3'])\n",
    "\n",
    "marker_text = []\n",
    "for i, card_string in enumerate(cards):\n",
    "\tcards = card_string.split(' ')\n",
    "\tassert(len(cards) == 6)\n",
    "\tmarker_text.append(f'Player Cards: {cards[:2]}, Community Cards: {cards[2:]}, Class: {raw_data_classes[i]}, EHS: {ehs_raw_data[i]:.2f}')\n",
    "\n",
    "# # https://stackoverflow.com/questions/61227248/plotly-how-to-create-custom-hover-labels-for-plotly-3d-scatter-figures\n",
    "fig = go.Figure()\n",
    "fig.add_trace(go.Scatter3d(x=PCs_3d[:, 0], y=PCs_3d[:,1], z=PCs_3d[:,2],\n",
    "                        hovertemplate='<b>%{text}</b><extra></extra>',\n",
    "                        text=marker_text,\n",
    "                        marker=dict(\n",
    "                            size=2,\n",
    "                            color=raw_data_classes\n",
    "                        ),\n",
    "                        mode='markers'\n",
    "))\n",
    "\n",
    "fig.update_layout(title=dict(text=f\"Turn Abstraction ({kmeans_centroids.shape[0]} Clusters)\", font=dict(size=28)), title_x=0.5, scene=dict(\n",
    "                  xaxis_title=\"Dimension 1\",\n",
    "                  yaxis_title=\"Dimension 2\",\n",
    "                  zaxis_title=\"Dimension 3\")\n",
    ")\n",
    "# fig.show()\n",
    "fig.show(renderer='browser')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.8 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
